Skip to content

gh-154002: Do not wrap a constructor TypeError in pickle._Unpickler - #154003

Open
fedonman wants to merge 3 commits into
python:mainfrom
fedonman:fix-gh-154002-pickle-instantiate-chaining
Open

gh-154002: Do not wrap a constructor TypeError in pickle._Unpickler#154003
fedonman wants to merge 3 commits into
python:mainfrom
fedonman:fix-gh-154002-pickle-instantiate-chaining

Conversation

@fedonman

@fedonman fedonman commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

_instantiate wrapped a constructor TypeError in a new one, passing the traceback as a
second argument, so the traceback object ended up in args and there was no chaining.

The wrapper is now gone and the original error propagates. Its purpose (743d17e, 1998)
was to name the class when __getinitargs__ returned something bogus, and the message
already carries the class name in that case, so the prefix repeated it:

pure Python: ('in constructor for WrongArgCount: WrongArgCount.__init__() takes 2 positional arguments but 3 were given', <traceback object at 0x762b6376b400>)
pure Python  args types: ['str', 'traceback']  cause=NoneType

The C unpickler never wrapped the error, so this also removes the divergence between the
two implementations. Both now give the same result for a bad argument count and for a
TypeError raised inside the constructor body.

The test asserts the original error reaches the caller unchanged. It fails on the
pure-Python unpickler without this change.

For the record, the traceback-in-args part is not from gh-102799 as the issue says. It
comes from 26d95c3, where raise T, V, tb became raise T(V, tb) rather than
raise T(V).with_traceback(tb). gh-102799 only changed sys.exc_info()[2] to
err.__traceback__.

…iate

When a class constructor raised TypeError during old-style (INST/OBJ)
unpickling, the pure-Python unpickler did
`raise TypeError(msg, err.__traceback__)`, which stored the traceback
object in the exception's args and performed no real chaining
(__cause__ stayed None). Use `raise TypeError(msg) from err` instead.
The C implementation is unaffected; it lets the original error propagate.
@fedonman

Copy link
Copy Markdown
Contributor Author

@zware part of EuroPython sprint.

The prefix repeats the class name that the constructor TypeError already
carries, and the C unpickler never wrapped the error, so letting the original
propagate removes the traceback-in-args bug and the divergence at once.
@fedonman fedonman changed the title gh-154002: Fix exception chaining in pickle _Unpickler._instantiate gh-154002: Do not wrap a constructor TypeError in pickle._Unpickler Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

2 participants